#include <GL/glut.h>
#include <stdlib.h>

#define MUNDO 4.0f
//Variables globales que guardan el tope de las coordenadas de mundo
float xMax, yMax;
float xRot, yRot, zRot, scale;
int solid;

void inicializar (void);
void redimensiona (int alto, int ancho);
void dibuja (void);
void teclado (unsigned char key, int cx, int cy);
void tecladoEspecial (int key, int cy, int cx);
void dibujaEscena (void);

int main(int argc, char** argv) {

   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (640, 480);
   glutInitWindowPosition (100, 105);
   glutCreateWindow ("Mesa con objetos");
   inicializar();

   glutDisplayFunc(dibuja);
   glutReshapeFunc(redimensiona);
   glutKeyboardFunc(teclado);
   glutSpecialFunc(tecladoEspecial);
   glutMainLoop();

   return 0;
}

void inicializar () {
   glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
   glEnable(GL_DEPTH_TEST);
   solid = 0;
   xRot = yRot = zRot = 0.0;
   scale = 1.0;
}

void redimensiona (int ancho, int alto) {
   float aspect;

   glViewport (0, 0, ancho, alto);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();

   if (alto == 0){
   	  alto = 1;
   }

   aspect = (float) ancho / (float) alto;

   if (ancho <= alto) {
   	  glOrtho(-MUNDO, MUNDO, -MUNDO/aspect, MUNDO/aspect, -MUNDO, MUNDO);
   	  xMax = MUNDO;
   	  yMax = MUNDO / aspect;

   } else {
   	  glOrtho(-MUNDO * aspect, MUNDO * aspect, -MUNDO, MUNDO, -MUNDO, MUNDO);
   	  xMax = MUNDO * aspect;
   	  yMax = MUNDO;
   }

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void teclado (unsigned char key, int cx, int cy) {

	switch (key) {
		case 27:
		   exit(0);
		break;

		case '+':
			scale += 0.1;
		break;

		case '-':
			scale -= 0.1;
		break;

		case 'o':
			solid = !(solid);
		break;

		default: break;
	}

	glutPostRedisplay();
}

void tecladoEspecial (int key, int cy, int cx) {

	switch (key) {
		case GLUT_KEY_UP:
			xRot -= 5.0;
		break;

		case GLUT_KEY_DOWN:
			xRot += 5.0;
		break;

		case GLUT_KEY_LEFT:
			yRot -= 5.0;
		break;

		case GLUT_KEY_RIGHT:
			yRot += 5.0;
		break;

		case GLUT_KEY_PAGE_UP:
			zRot += 5.0;
		break;

		case GLUT_KEY_PAGE_DOWN:
			zRot -= 5.0;
		break;

		default: break;
	}

	glutPostRedisplay();
}

void dibuja (void) {

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glPushMatrix();
		glRotatef(xRot, 1.0, 0.0, 0.0);
		glRotatef(yRot, 0.0, 1.0, 0.0);
		glRotatef(zRot, 0.0, 0.0, 1.0);
		glScalef(scale, scale, scale);
		dibujaEscena();
	glPopMatrix();

	glFlush();
}

void dibujaEscena () {

	glPushMatrix();

		//Mesa
		glColor3f(0.9, 0.66, 0.07);
		glPushMatrix();
			glTranslatef(0.0, 2.0, 0.0);
			glScalef(5.0, 0.5, 5.0);
			solid ? glutSolidCube(1.0) : glutWireCube(1.0);
		glPopMatrix();

		//Patas de la mesa
		glPushMatrix();
			glTranslatef(2.0, -0.25, 2.0);
			glScalef(0.7, 4.0, 0.7);
			solid ? glutSolidCube(1.0) : glutWireCube(1.0);
		glPopMatrix();
		glPushMatrix();
			glTranslatef(2.0, -0.25, -2.0);
			glScalef(0.7, 4.0, 0.7);
			solid ? glutSolidCube(1.0) : glutWireCube(1.0);
		glPopMatrix();
		glPushMatrix();
			glTranslatef(-2.0, -0.25, 2.0);
			glScalef(0.7, 4.0, 0.7);
			solid ? glutSolidCube(1.0) : glutWireCube(1.0);
		glPopMatrix();
		glPushMatrix();
			glTranslatef(-2.0, -0.25, -2.0);
			glScalef(0.7, 4.0, 0.7);
			solid ? glutSolidCube(1.0) : glutWireCube(1.0);
		glPopMatrix();

		//Una tetera sobre la mesa
		glColor3f(1.0, 0.0, 0.0);
		glPushMatrix();
			glTranslatef(0.0, 2.65, 0.0);
			glScalef(0.5, 0.5, 0.35);
			solid ? glutSolidTeapot(1.0) : glutWireTeapot(1.0);
		glPopMatrix();

		//Un icosahedro, tambien sobre la mesa
		glColor3f(0.0, 1.0, 0.0);
		glPushMatrix();
			glTranslatef(2.0, 2.65, 2.0);
			glScalef(0.5, 0.5, 0.5);
			solid ? glutSolidIcosahedron() : glutWireIcosahedron();
		glPopMatrix();
		
	glPopMatrix();
}
